#pragma once


#include<string>
#include<iostream>

using namespace std;

namespace yyh
{
	template<class T>
	struct list_node
	{
		T _data;
		list_node<T>* _prev;
		list_node<T>* _next;

		list_node(const T& data = T())
			:_data(data)
			, _prev(nullptr)
			, _next(nullptr)
		{ }

		template<class... Args>
		list_node(Args&&... args)
			:_data(forward<Args>(args)...)
			, _prev(nullptr)
			, _next(nullptr)
		{ }
	};

	template<class T, class Ptr, class Ref>
	struct list_iterator
	{
		typedef list_node<T> Node;
		typedef list_iterator<T, Ptr, Ref> Self;

		Node* _node;

		list_iterator(Node* node)
			:_node(node)
		{ }

		Ref operator*()
		{
			return _node->_data;
		}

		Ptr operator->()
		{
			return &_node->_data;
		}

		Self operator++()
		{
			_node = _node->_next;
			return *this;
		}

		bool operator!=(const Self& s)
		{
			return _node != s._node;
		}

		bool operator==(const Self& s)
		{
			return _node == s._node;
		}
	};

	template<class T>
	class list
	{
		typedef list_node<T> Node;
	public:
		typedef list_iterator<T, T*, T&> iterator;

		iterator begin()
		{
			return iterator(_head->_next);
		}

		iterator end()
		{
			return iterator(_head);
		}

		void empty_init()
		{
			_head = new Node;
			_head->_prev = _head->_next = _head;
			_size = 0;
		}

		list()
		{
			empty_init();
		}

		template<class... Args>
		void emplace_back(Args&&... args)
		{
			emplace(end(), forward<Args>(args)...);
		}

		template<class... Args>
		void emplace(iterator pos, Args&&... args)
		{
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* new_node = new Node(forward<Args>(args)...);

			prev->_next = new_node;
			new_node->_prev = prev;
			new_node->_next = cur;
			cur->_prev = new_node;

			_size++;
		}

		void push_back(const T& data)
		{
			insert(end(), data);
		}

		void insert(iterator pos, const T& data)
		{
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* new_node = new Node(data);

			prev->_next = new_node;
			new_node->_prev = prev;
			new_node->_next = cur;
			cur->_prev = new_node;

			_size++;
		}

	private:
		Node* _head;
		size_t _size;
	};

	void test1()
	{
		list<string> lt;
		lt.emplace_back("one");
		lt.emplace_back("two");
		lt.emplace_back("three");
		lt.emplace_back("four");
		for (auto& e : lt)
		{
			cout << e << ' ';
		}
		cout << endl;
		lt.emplace(lt.end(), "five");
		for (auto& e : lt)
		{
			cout << e << ' ';
		}
		cout << endl;
		list<string>::iterator it = lt.begin();
		lt.emplace(it, "six");
		for (auto& e : lt)
		{
			cout << e << ' ';
		}
		cout << endl;
		lt.emplace(++it, "seven");
		for (auto& e : lt)
		{
			cout << e << ' ';
		}
		cout << endl;
	}
}